from Accounting.Fee.FeeBase import Fee
from Accounting.CashFlow.SubRed import *
from Accounting.Entity.Utils import *
from DataAccess.DBConnFactory import DBConnFactory
from string import Template


class ClientFixedFeeRebate(Fee):

	def __init__(self, ref_date, entity, subtype, is_payment_date, is_redem, curncy):
	
		cursor = DBConnFactory().get_db_connection('ACCOUNTING').cursor()
		sql_tpl = Template('''select parent_feetp4_rebate,rebate_ratio,curncy from fee_conf
							where entity='${ENTITY}'
								and subtype='${TP}' ''')			
		cursor.execute(sql_tpl.substitute(ENTITY=entity.get_entity_id(), 
										TP=subtype))
		r = cursor.fetchall()
		if not r:
			raise RuntimeError(), ("Fee Config Error")
		self.parent_subtype = r[0][0]
		self.rebate_ratio = r[0][1]
		self.fee_subtype = subtype
		
		Fee.__init__(self, ref_date, r[0][2], is_payment_date, is_redem, entity)
		
	def calculate(self):
		
		parent = self.entity.get_parent()
		cursor = DBConnFactory().get_db_connection('ACCOUNTING').cursor()
		
		sql_tpl = Template('''select amount from fee_ex
							where ref_date=TO_DATE('${DATE}','yyyy-mm-dd')
								and	entity='${ENTITY}' 
								and	subtype='${TP}' ''')
		cursor.execute(sql_tpl.substitute(DATE=self.ref_date.isoformat(), 
										ENTITY=parent.get_entity_id(), 
										TP=self.parent_subtype))
		r = cursor.fetchall()
		if not r:
			raise RuntimeError(), ("Fixed Fee Error")
		parent_fee = r[0][0]
		
		sql_tpl = Template('''select shares/sum_shares from
							share_account,		
							(select sum(shares) as sum_shares from share_account
								where parent='${PARENT}' 
									and ref_date=TO_DATE('${DATE}','yyyy-mm-dd')-1)
							where child='${CHILD}'  
								and ref_date=TO_DATE('${DATE}','yyyy-mm-dd')
								and shares<>0''')
		cursor.execute(sql_tpl.substitute(DATE=self.ref_date.isoformat(), 
										PARENT=parent.get_entity_id(), 
										CHILD=self.entity.get_entity_id()))
		r = cursor.fetchall()
		if not r:
			raise RuntimeError(), ("Share Account Error")
		child_share_weight = r[0][0]
		
		self.amt = -parent_fee*child_share_weight*self.rebate_ratio
		
	def type(self):
		return self.fee_subtype
		
	def category(self):
		return 'PreIAVFee'


class ClientFloatFeeAdj(Fee):

	def __init__(self, ref_date, entity, subtype, is_payment_date, is_redem, curncy):
	
		cursor = DBConnFactory().get_db_connection('ACCOUNTING').cursor()
		sql_tpl = Template('''select perf_ratio,subtype,curncy 
							from fee_conf,
							(select parent_feetp4_perfadj from fee_conf
								where entity='${CHILD}'
									and subtype='${TP}') t
							where entity='${PARENT}'
								and subtype=t.parent_feetp4_perfadj ''')	

		#print entity.get_entity_id(), subtype, entity.get_parent().get_entity_id()
		cursor.execute(sql_tpl.substitute(CHILD=entity.get_entity_id(), 
										TP=subtype,
										PARENT=entity.get_parent().get_entity_id()))
		r = cursor.fetchall()
		if not r:
			raise RuntimeError(), ("Fee Config Error")
		
		self.perf_ratio = r[0][0]
		self.parent_subtype = r[0][1]
		self.fee_subtype = subtype
		
		Fee.__init__(self, ref_date, r[0][2], is_payment_date, is_redem, entity)
		
	def calculate(self):
		cursor = DBConnFactory().get_db_connection('ACCOUNTING').cursor()
		
		self.amt = 0
		parent = self.entity.get_parent()
		pre_peak = watermark(self.ref_date, parent ,self.parent_subtype)
		crt_GAV_per_share = GAV_per_share(self.ref_date, parent)
	
		#Select Remaining Shares After Pre-peak
		sql_tpl =Template('''select id,shares,max(high_avpu) 
							from (
								select rs.id,rs.ref_date,rs.shares,
								decode(sign(NVL(av1.avpu,0)-NVL(av2.avpu,0)),1,NVL(av1.avpu,0),NVL(av2.avpu,0)) as high_avpu
								from feeder_remain_share rs
								left join
									fee_schedule_ex fs
								on fs.entity=rs.child
									and fs.ref_date>rs.ref_date
									and fs.ref_date<TO_DATE('${END}','yyyy-mm-dd')	
									and fs.subtype='${FSTP}'
									and fs.is_pay_day='T'
								left join
									asset_value_ex av1
								on av1.ref_date=rs.ref_date
									and av1.entity=rs.parent
									and av1.type='${TP}'
								left join 
									asset_value_ex av2
								on av2.ref_date=fs.ref_date
									and av2.entity=rs.parent
									and av2.type='${TP}'								
								where
									rs.child='${ENTITY}' 
									and rs.ref_date>TO_DATE('${START}','yyyy-mm-dd') 
									and rs.ref_date<TO_DATE('${END}','yyyy-mm-dd') 
							) group by id,shares''')					
		sql_text = sql_tpl.substitute(TP='GAV',
									ENTITY = self.entity.get_entity_id(),
									FSTP = self.fee_subtype,
									START = pre_peak[0].date().isoformat(),
									END = self.ref_date.isoformat())
		cursor.execute(sql_text)		
		r = cursor.fetchall()
		
		#Perf Adjustment for each subscription
		self.perf_adj = {}
		for each in r:
			perf_adj_one_sub=(max(crt_GAV_per_share-each[2], 0)
							-max(crt_GAV_per_share-pre_peak[1], 0))*each[1]*self.perf_ratio	
			self.amt += perf_adj_one_sub
			self.perf_adj[each[0]] = perf_adj_one_sub
			
			#print 'debug, perf_adj', self.perf_adj
			#if self.entity.get_entity_id() == 'HML0387711':
			#	print 'debug, ref_date=', self.ref_date.isoformat()
			#	print 'debug, client=', self.entity.get_entity_id()
			#	print 'debug, crt_GAV_per_share=', crt_GAV_per_share
			#	print 'debug, GAV_of_sub=', each[2]
			#	print 'debug, pre_peak=', pre_peak[1]
			#	print 'debug, shares_of_sub=', each[1]
							
							
	def trigger_fund_share_chg(self, ref_date):
		if not self.is_pay_date():
			return []
		
		act=[]
		curncy = self.currency()
		conv_by = share_amt_conv_type(ref_date, self.entity)
		sub_amt_sum = 0.0
		for id,amount in self.perf_adj.iteritems():		
			if self.cash_redeming():
				if amount > 0:
					#print 'debug, Redemption=', amount
					assert id
					act.append(Redemption(ref_date, amount, curncy, RedemptionByAmount, 
									id, conv_by, self.entity, self.type()))						
				elif amount < 0:
					sub_amt_sum += abs(amount)
					#act.append(Subscription(ref_date, -1*amount, curncy, conv_by, 
					#					self.entity, self.type()))
				else:
					pass
		
		if sub_amt_sum > 0:
			act.append(Subscription(ref_date, sub_amt_sum, curncy, conv_by, 
								self.entity, self.type()))
								
		return act				
					
					
	def type(self):
		return self.fee_subtype
		
	def category(self):
		return 'PreIAVFee'
		
		
		
